﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using SharedGenomics.Workbench.Core;

namespace SharedGenomics.Workbench.Tests.Core
{
    [TestClass]
    public class MaybeTests
    {
        [TestMethod]
        public void ShouldHaveValue()
        {
            Maybe<string> m = new Maybe<string>("abc");
            Assert.IsTrue(m.HasValue);
        }

        [TestMethod]
        public void ShouldNotHaveValue()
        {
            Maybe<string> m = new Maybe<string>();
            Assert.IsFalse(m.HasValue);
        }

        [TestMethod]
        public void ShouldReturnValue()
        {
            Maybe<string> m = new Maybe<string>("abc");
            Assert.AreEqual("abc", m.Value);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void ShouldThrowIfNoValue()
        {
            Maybe<string> m = new Maybe<string>();
            string val = m.Value;
        }

        [TestMethod]
        public void ShouldExecuteReturnAction()
        {
            bool executed = false;
            Maybe<string> m = new Maybe<string>("abc");
            m.BindAction(str => { executed = true; });

            Assert.IsTrue(executed, "Action not executed");
        }

        [TestMethod]
        public void ShouldExecuteFailureAction()
        {
            bool executed = false;
            Maybe<string> m = new Maybe<string>();
            m.BindAction(str => { }, () => { executed = true; });

            Assert.IsTrue(executed, "Failure action not executed");
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BindActionShouldThrowIfNull()
        {
            Maybe<string> m = null;
            m.BindAction(str => { });
        }

        [TestMethod]
        public void ShouldPropagateNone()
        {
            Maybe<string> m = new Maybe<string>();
            var outMaybe = m.Bind(s => int.Parse(s));
            Assert.IsFalse(outMaybe.HasValue, "Returned maybe is not None");
        }

        [TestMethod]
        public void ShouldReturnTransformedMaybe()
        {
            Maybe<string> m = "123".Just();
            var outMaybe = m.Bind(s => int.Parse(s));
            Assert.AreEqual(123, outMaybe.Value);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BindShouldThrowIfNull()
        {
            Maybe<string> m = null;
            m.Bind(s => s);
        }
    }
}
